/// ------------------------------------------------------------------------------------------------------------------------------------
///
/// MIT License
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
/// Copyright (c) 2024 ycz. All rights reserved.
///
/// Created by ycz on 24-11-7.
///
/// @file  app_uart.c
///
/// @brief
///     应用层 串口配置 实现
///
/// ------------------------------------------------------------------------------------------------------------------------------------



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 头文件
/// ------------------------------------------------------------------------------------------------------------------------------------

#include "app_uart.h"

#include <string.h>
#include "y_sa.h"
#include "app.h"
#include "usart.h"



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 全局变量
/// ------------------------------------------------------------------------------------------------------------------------------------

static APP_UART_CONFIG_st g_default_config = {
        .baudrate_1 = 921600,  ///< 波特率 串口 1
        .baudrate_2 = 0,       ///< 波特率 串口 2
        .baudrate_3 = 0,       ///< 波特率 串口 3
        .baudrate_4 = 0,       ///< 波特率 串口 4
        .baudrate_5 = 0,       ///< 波特率 串口 5
        .baudrate_6 = 9600,    ///< 波特率 串口 6
};  ///< 默认参数
static APP_UART_CONFIG_st g_config;         ///< 全局参数
static uint8_t            uart1_buf[2048];  ///< 串口 buf
static uint8_t            uart6_buf[2048];  ///< 串口 buf



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 公有函数
/// ------------------------------------------------------------------------------------------------------------------------------------

/// @brief   打印 app_uart 版本信息
void app_uart_print_version() {
    YLOG_VERSION("app_uart", APP_UART_MAJOR, APP_UART_MINOR, APP_UART_PATCH);
}

/// @brief   串口中断处理
/// @param   [in] uart_num                 串口编号
void app_uart_irq_cb(UART_NUM_e uart_num) {

    // 处理中断
    switch (uart_num) {
        case UART_1: {
            extern DMA_HandleTypeDef hdma_usart1_rx;
            HAL_UART_DMAStop(&huart1);                                                   // 处理时暂停 DMA 接收
            uint16_t size = sizeof(uart1_buf) - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);  // 计算接收到的数据长度
            y_cli_parse(uart1_buf, size);                                                // 命令行添加数据
            HAL_UART_Receive_DMA(&huart1, uart1_buf, sizeof(uart1_buf));                 // 打开 DMA 接收
        } break;
        case UART_2:
            break;
        case UART_3:
            break;
        case UART_4:
            break;
        case UART_5:
            break;
        case UART_6: {
            extern DMA_HandleTypeDef hdma_usart6_rx;
            HAL_UART_DMAStop(&huart6);                                                   // 处理时暂停 DMA 接收
            uint16_t size = sizeof(uart6_buf) - __HAL_DMA_GET_COUNTER(&hdma_usart6_rx);  // 计算接收到的数据长度
            y_modbus_add_data(app_modbus_get_slave_handle(), uart6_buf, size);           // modbus 添加数据
            HAL_UART_Receive_DMA(&huart6, uart6_buf, sizeof(uart6_buf));                 // 打开 DMA 接收
        } break;
    }
}

/// @brief   串口发送数据
/// @param   [in] uart_num                 串口编号
/// @param   [in] data                     数据指针
/// @param   [in] size                     数据大小
/// @retval  true                          成功
/// @retval  false                         失败
bool app_uart_send(UART_NUM_e uart_num, uint8_t *data, uint16_t size) {

    // 断言
    YLOGA_FALSE(data);
    YLOGA_FALSE(size);

    switch (uart_num) {
        case UART_1: {
            return HAL_UART_Transmit(&huart1, data, size, 100) == HAL_OK ? true : false;
        } break;
        case UART_2:
            break;
        case UART_3:
            break;
        case UART_4:
            break;
        case UART_5:
            break;
        case UART_6:
            return HAL_UART_Transmit(&huart6, data, size, 100) == HAL_OK ? true : false;
    }

    return false;
}

/// @brief   获取串口波特率
/// @param   [in] uart_num                 串口编号
/// @return  波特率
uint32_t app_uart_get_baudrate(UART_NUM_e uart_num) {
    switch (uart_num) {
        case UART_1:
            return g_config.baudrate_1;
        case UART_2:
            return g_config.baudrate_2;
        case UART_3:
            return g_config.baudrate_3;
        case UART_4:
            return g_config.baudrate_4;
        case UART_5:
            return g_config.baudrate_5;
        case UART_6:
            return g_config.baudrate_6;
    }
    return 0;
}

/// @brief   设备串口波特率
/// @param   [in] uart_num                 串口编号
/// @param   [in] baudrate                 波特率
/// @retval  true                          成功
/// @retval  false                         失败
bool app_uart_set_baudrate(UART_NUM_e uart_num, uint32_t baudrate) {

    UART_HandleTypeDef *huart = NULL;

    switch (uart_num) {
        case UART_1:
            huart               = &huart1;
            huart->Instance     = USART1;
            g_config.baudrate_1 = baudrate;
            break;
        case UART_2:
            break;
        case UART_3:
            break;
        case UART_4:
            break;
        case UART_5:
            break;
        case UART_6:
            huart               = &huart6;
            huart->Instance     = USART6;
            g_config.baudrate_6 = baudrate;
            break;
    }

    // 断言串口句柄
    YLOGA_FALSE(huart);

    // 设置波特率
    huart->Init.BaudRate     = baudrate;
    huart->Init.WordLength   = UART_WORDLENGTH_8B;
    huart->Init.StopBits     = UART_STOPBITS_1;
    huart->Init.Parity       = UART_PARITY_NONE;
    huart->Init.Mode         = UART_MODE_TX_RX;
    huart->Init.HwFlowCtl    = UART_HWCONTROL_NONE;
    huart->Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_DeInit(huart);  // 关闭已打开的串口
    if (HAL_UART_Init(huart) != HAL_OK) {
        return false;
    }

    // 保存到 nvs
    y_nvs_set((uint8_t *) "uart_config", (uint8_t *) &g_config, sizeof(g_config), true);

    return true;
}

/// @brief   打印参数
/// @param   [in] config                   参数
void app_uart_config_print(APP_UART_CONFIG_st *config) {
    // 断言
    YLOGA(config);
    if (config->baudrate_1) {
        YLOGI("UART baudrate_1                   : %u", config->baudrate_1);
    }
    if (config->baudrate_2) {
        YLOGI("UART baudrate_2                   : %u", config->baudrate_2);
    }
    if (config->baudrate_3) {
        YLOGI("UART baudrate_3                   : %u", config->baudrate_3);
    }
    if (config->baudrate_4) {
        YLOGI("UART baudrate_4                   : %u", config->baudrate_4);
    }
    if (config->baudrate_5) {
        YLOGI("UART baudrate_5                   : %u", config->baudrate_5);
    }
    if (config->baudrate_6) {
        YLOGI("UART baudrate_6                   : %u", config->baudrate_6);
    }
}

/// @brief   参数获取
/// @return  参数值
APP_UART_CONFIG_st *app_uart_config_get() {
    return &g_config;
}

/// @brief   参数设置
/// @param   [in] config                   参数
/// @retval  true                          成功
/// @retval  false                         失败
bool app_uart_config_set(APP_UART_CONFIG_st *config) {
    // 断言
    YLOGA_FALSE(config);
    memcpy(&g_config, config, sizeof(g_config));  // 参数赋值
    return y_nvs_set((uint8_t *) "uart_config", (uint8_t *) &g_config, sizeof(g_config), true);
}

/// @brief   初始化
/// @retval  true                          成功
/// @retval  false                         失败
bool app_uart_init() {

    // 加载算法参数
    uint16_t size = 0;
    if (y_nvs_get((uint8_t *) "uart_config", (uint8_t *) &g_config, &size) == false || size != sizeof(g_config)) {  // 从 nvs 读取失败
        memcpy(&g_config, &g_default_config, sizeof(g_config));
        y_nvs_set((uint8_t *) "uart_config", (uint8_t *) &g_config, sizeof(g_config), true);
    }
    // jt_uart_config_print(&g_config);

    // 重新设置波特率
    app_uart_set_baudrate(UART_1, g_config.baudrate_1);
    app_uart_set_baudrate(UART_2, g_config.baudrate_2);
    app_uart_set_baudrate(UART_3, g_config.baudrate_3);
    app_uart_set_baudrate(UART_4, g_config.baudrate_4);
    app_uart_set_baudrate(UART_5, g_config.baudrate_5);
    app_uart_set_baudrate(UART_6, g_config.baudrate_6);

    // 打开串口中断
    HAL_UART_Receive_DMA(&huart1, uart1_buf, sizeof(uart1_buf));  // 打开 DMA 接收
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);                  // 使能 uart idle中断
    HAL_UART_Receive_DMA(&huart6, uart6_buf, sizeof(uart6_buf));  // 打开 DMA 接收
    __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);                  // 使能 uart idle中断

    return true;
}